﻿#include <stdio.h>
#include <Windows.h>
#include <conio.h>
//游戏数据
#define MAPSIZE  19//地图边长
int g_gamer;//g_gamer==1代表黑方；g_gamer==2代表白方
int g_x;//光标位置横坐标
int g_y;//光标位置纵坐标
int g_chessboard[MAPSIZE][MAPSIZE];//棋盘数据
int g_count;//落子数
//函数
void DrawMap();//地图绘制
int Put();//落子
void RunGame();//对战模块
void StartGame();//游戏初始化
int WOrL(int x, int y);//输赢判断

int main()
{
	SetConsoleTitle(L"欢乐五子棋");//设置窗口标题
	system("mode con cols=50 lines=30");//设置窗口大小
	system("color 20");//设置背景颜色为护眼绿色
	while (1)
	{
		RunGame();//对战
	};//防闪退
	return 0;
}

//对战模块
void RunGame()
{
	StartGame();//初始化棋盘
	//获取横、纵坐标值
	while (1)
	{
		system("cls");//清除上一次绘图信息
		DrawMap();//绘制棋盘
		char input = _getch();//光标移动信息，符号“╳”代表光标
		switch (input)
		{
		case 32://空格落子
			if (Put())
			{
				//输赢判断
   				if (WOrL(g_x, g_y))
				{	
						switch (g_count%2)
						{
						case 0:
							MessageBox(NULL, L"黑棋胜", L"游戏结束", MB_OK);
							exit(0);
							break;
						case 1:
							MessageBox(NULL, L"白棋胜", L"游戏结束", MB_OK);
							exit(0);
							break;
						default:
							break;
						}	
				}
				g_count++;//落子数+1
				//玩家交换
				if (g_gamer == 1)
				{
					g_gamer = 2;
				}
				else
				{
					g_gamer = 1;
				}
			}
			else
			{
				MessageBox(NULL, L"该处已落子，请重新选择落子位置", L"系统提示", MB_OK);//落子重叠提示
				continue;//重新进入循环
			}
			break;
		case 72://上键上移
			g_x--;
			if (g_x < 0)
				g_x = MAPSIZE - 1;
			break;
		case 80://下键下移
			g_x++;
			if (g_x > MAPSIZE - 1)
				g_x = 0;
			break;
		case 75://左键左移
			g_y--;
			if (g_y < 0)
				g_y = MAPSIZE - 1;
			break;
		case 77://右键右移
			g_y++;
			if (g_y > MAPSIZE - 1)
				g_y = 0;
			break;
		default:
			break;
		}
	}
}

//游戏初始化
void StartGame()
{
	g_chessboard[MAPSIZE][MAPSIZE] = { 0 };//棋盘数据归0
	g_x = g_y = MAPSIZE / 2;//光标居中
	g_count = 0;//初始化落子数
	g_gamer = 1;//黑棋先落子
}

//绘制棋盘
void DrawMap()
{
	for (int i = 0; i < MAPSIZE; i++)
	{
		for (int j = 0; j < MAPSIZE; j++)
		{
			if (i == g_x && j == g_y && g_chessboard[i][j] == 0)
			{
				printf("╳ ");//设置光标
			}
			else if (g_chessboard[i][j] == 1)//打印黑棋
			{
				printf("●");
			}
			else if (g_chessboard[i][j] == 2)//打印白棋
			{
				printf("○");
			}
			else if (i == 0 && j == 0)
			{
				printf("┌ ");
			}
			else if (i == 0 && j == MAPSIZE - 1)
			{
				printf("┐");
			}
			else if (i == MAPSIZE - 1 && j == 0)
			{
				printf("└ ");
			}
			else if (i == MAPSIZE - 1 && j == MAPSIZE - 1)
			{
				printf("┘");
			}
			else if (i == 0)
			{
				printf("┬ ");
			}
			else if (j == 0)
			{
				printf("├ ");
			}
			else if (i == MAPSIZE - 1)
			{
				printf("┴ ");
			}
			else if (j == MAPSIZE - 1)
			{
				printf("┤");
			}
			else if (g_chessboard[i][j] == 0)
			{
				printf("┼ ");
			}
		}
		printf("\n");
	}

}

//落子；落子成功返回1.失败返回0
int Put()
{
	if (g_chessboard[g_x][g_y] == 0)//有空位落子
	{
		g_chessboard[g_x][g_y] = g_gamer;//当前玩家落子
		return 1;
	}
	else
	{
		return 0;
	}
}

//输赢判断,分出输赢返回1，平局直接打印“平局”，否则返回0
int WOrL(int x, int y)
{
	int i, j;
	int count;//循环遍历次数
	int winNum = 1;//胜利者此时的棋子数
	int t = g_chessboard[x][y];//获取当前棋子信息，黑棋还是白棋
	//纵向五子连珠
	count = 0;
	for (i = x - 1, j = y; i > 0 && count++ < 5; i--)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;
			
		}
		else
		{
			break;
		}
	}
	count = 0;
	for (i = x + 1, j = y; i < MAPSIZE && count++ < 5; i++)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;
			
		}
		else
		{
			break;
		}
	}
	if (winNum >= 5)
	{
		return 1;
	}
	else
	{
		winNum = 1;
	}
	//横向五子连珠
	count = 0;
	for (i = x , j = y - 1; j > 0 && count++ < 5; j--)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;
		
		}
		else
		{
			break;
		}
	}
	count = 0;
	for (i = x, j = y + 1; j < MAPSIZE && count++ < 5; j++)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;
			
		}
		else
		{
			break;
		}
	}
	if (winNum >= 5)
	{
		return 1;
	}
	else
	{
		winNum = 1;
	}
	//左斜向五子连珠
	count = 0;
	for (i = x - 1, j = y - 1; i > 0 && j > 0 && count++ < 5; i-- , j--)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;
		}
		else
		{
			break;
		}
	}
	count = 0;
	for (i = x + 1, j = y + 1; i < MAPSIZE && j < MAPSIZE && count++ < 5; i++, j++)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;
			
		}
		else
		{
			break;
		}
	}
	if (winNum >= 5)
	{
		return 1;
	}
	else
	{
		winNum = 1;
	}
	//右斜向五子连珠
	count = 0;
	for (i = x + 1, j = y - 1; i < MAPSIZE && j > 0 && count++ < 5; i++, j--)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;
		}
		else
		{
			break;
		}
	}
	count = 0;
	for (i = x - 1, j = y + 1; i > 0 && j < MAPSIZE && count++ < 5; i--, j++)
	{
		if (g_chessboard[i][j] == t)
		{
			winNum++;

		}
		else
		{
			break;
		}
	}
	if (winNum >= 5)
	{
		return 1;
	}
	else
	{
		winNum = 1;
	}
	//平局判断
	if (g_count >= MAPSIZE * MAPSIZE)
	{
		MessageBox(NULL, L"平局", L"游戏结束", MB_OK);
		exit(0);
	}
	//未分出胜负
	return 0;
}